/*
 * @(#)Lock.java	20.06.1997  Robert Denda
 *
 */

/**
 * Ein Lock ist eine Erweiterung zu den bereits bestehenden Thread-Synchronisationsmechanismen.
 * Es wird dann benötigt, wenn mehrere Threads Funktionen innerhalb einer Java Klasse ausfuehren
 * sollen, eine komplette Synchronisation mittels "synchronized" die potentielle Parallelität zu
 * stark einschränken würde.
 *
 * @author 	Robert Denda
 * @version     1.0, 20.06.1997
 */

public class Lock {
  
  private Thread holder;
  private int acquiredCount = 0;

  public Lock() {
    holder = null;
  } // Lock.Lock

  /**
   * Bei einem Aufruf von acquire() blockt der aufrufende Thread, wenn er nicht der Halter des 
   * Locks ist, bis der Halter durch einen Aufruf von release() das Lock wieder freigibt.
   * Der Halter des Locks blockt nicht bei einem erneuten Aufruf von acquire(), muß dann aber 
   * ein weiteres release() tätigen bevor das Lock freigegeben wird.
   *
   * @see Lock#release
   */

  public synchronized final void acquire() {
    if ( holder != null && holder.equals( Thread.currentThread() ) ) {
      acquiredCount += 1;
      return;
    } // if
    while ( acquiredCount != 0 ) {
      try { 
	wait();
      } catch( InterruptedException e ) {
      } // try
    } // while
    acquiredCount += 1;
    holder = Thread.currentThread();
  } // Lock.acquire

  /**
   * release() gibt das durch ein vorangegangenes acquire() bekommene Lock wieder frei.  Nur der
   * holder des Locks kann es freigeben
   * 
   * @see Lock#release
   */

  public synchronized final void release() {
    if ( !holder.equals( Thread.currentThread() ) ) {
      System.err.println( Thread.currentThread().getName() + " tried to release " + this 
			  + "but holder of it is " + holder.getName() );
      return;
    } // if
    acquiredCount -= 1;
    if ( acquiredCount == 0 ) {
      holder = null;
      notifyAll();
    } // if
  } // Lock.release

} // Lock
